#ifndef __PARSEMESSAGE_H__
#define __PARSEMESSAGE_H__

#include "common.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <queue>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

class HttpResponse
{
  public:
    HttpResponse();

    void clear();

    std::string& getRespLine();
    const std::vector<std::string>& getRespHeader();
    void addRespHeader(std::string& str);
    const std::string& getRespBlank ();
  private:
    std::string resp_line_;
    std::vector<std::string> resp_header_;
    std::string blank_;
    std::string resp_body_;
};

class HttpRequest
{
  public:
    HttpRequest();
    ~HttpRequest();

    void clear();

    bool isLegalMethod();
    bool isGetMethod();
    bool isPostMethod();

    std::string getPath();
    void setPath(const std::string& path);
    bool getCgi();
    void setCgi();
    void setFileSize(size_t size);
    std::string getPathSuffix();
    size_t getFileSize();
    const std::string& getMethod();
    const std::string& getParam();
    const std::string& getBody();

    bool parseUrl();
    bool setUrlToPath();
    void addHomePage();
    bool parseReqMsg(const char* msg, int msglen);
  private:
    std::string req_line_;//请求行
    std::vector<std::string> req_header_;//请求报头
    std::string req_blank_;//空行
    std::string req_body_;//请求正文

  private:
    std::string method_;
    std::string url_;
    std::string version_;
    
    std::string path_;//请求资源路径
    std::string param_;//参数
    bool iscgi_;//是否使用cgi技术
    size_t filesize_;
  private:
    std::map<std::string, std::string> header_map_;
    uint32 content_length_;//正文长度

};

class HttpEndPoint
{
  public:
    HttpEndPoint(int sock = 0);
    ~HttpEndPoint();
    bool parseHttpMsg(const char* msg, int msglen);
    
    void clear();
    void setHttpEndPoint(int sock);

    bool handleRequest(const char* msg, int msglen);
    bool makeRespLine(size_t code);
    bool makeRespHeader();
    bool makeResponse();//加入到epoll中

    bool sendResponse();

    bool exeNoCgi();
    bool exeCgi();
  private:
    HttpResponse resp_;
    HttpRequest req_;
    int sock_;
};


class ParseMessage 
{
public:
  ParseMessage();
  ~ParseMessage();
  //自定义协议 报头(一字节保存正文长度)+正文
  //去掉static试下
  static void parseUserCmd(const char* cmd, int cmdLen);
  static void loginTask(const char* cmd, int cmdLen);
  static void userRegister(const char* cmd, int cmdLen);
  static void userLogin(const char* cmd, int cmdLen);

private:
};

class HttpMessageQueue : public qSingleton<HttpMessageQueue>
{
  friend class qSingleton<HttpMessageQueue>;  
private:
  HttpMessageQueue()
  {
    pthread_mutex_init(&mt_, nullptr);
    //pthread_mutex_init(&num_mt_, nullptr);
  }
  HttpMessageQueue& operator=(const HttpMessageQueue&);
  HttpMessageQueue(const HttpMessageQueue&);
public:
  ~HttpMessageQueue()
  {
    for(auto& c : endpoint_map_)
    {
      while(!c.second.empty())
      {
        HttpEndPoint* e = c.second.front();
        delete e;
        c.second.pop();
      }
    }
    pthread_mutex_destroy(&mt_);
    //pthread_mutex_destroy(&num_mt_);
  }
  HttpEndPoint* getEndPoint(int sock);
  bool endPointExist(int sock);
  void addEndPoint(int sock, HttpEndPoint* e);
  //void subEndPointNum(int sock);
  //void addEndPointNum(int sock);
  int getSockEndPointNum(int sock);
  bool isEmpty(int sock);
protected:
  std::map<int, std::queue<HttpEndPoint*> > endpoint_map_; 
  pthread_mutex_t mt_;
  //std::map<int, int> sock_num_;//只有delete时会减个数
  //pthread_mutex_t num_mt_;//sock操作数锁
};


#endif
